/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2008, 2009, 2010.

	This file is part of the Maxsi Library.

	Maxsi Library is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi Library is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
	or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
	License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Library. If not, see <http://www.gnu.org/licenses/>.

	Maxsi Library
	A powerful Cross-Platform C++ General Purpose Library that allows you to
	efficiently create high-performance and reliable applications.

	MaxsiHTTP.h
	A simple system for downloading stuff through the Hypertext Transfer
	Protocol. Conditional RFC 2616 compliance is attempted.

******************************************************************************/

#ifndef MaxsiHTTP_H
#define MaxsiHTTP_H

BeginMaxsiNamespace

#ifdef Maxsi_Using_Unicode_Internally

	#define Maxsi__SetURLM SetURLW
	#define Maxsi__CompareURLsM CompareURLsW

#else

	#define Maxsi__SetURLM SetURLA
	#define Maxsi__CompareURLsM CompareURLsA

#endif

#ifdef Maxsi_Enable_Non_Namespaced_Macros

	#define SetURLM Maxsi__SetURLM
	#define CompareURLsM Maxsi__CompareURLsM 

#endif

#define MAXSI_HTTP_STATE_CONNECTING 0
#define MAXSI_HTTP_STATE_BUILDING_REQUEST 1
#define MAXSI_HTTP_STATE_SENDING_REQUEST 2
#define MAXSI_HTTP_STATE_STATUS_LINE 3
#define MAXSI_HTTP_STATE_HEADERS 4
#define MAXSI_HTTP_STATE_BODY 5
#define MAXSI_HTTP_STATE_DONE 6

#define MAXSI_HTTP_TRANSFER_ENCODING_IDENTITY 0
#define MAXSI_HTTP_TRANSFER_ENCODING_CHUNKED 1

#define MAXSI_HTTP_CHUNKED_READING_CHUNK_SIZE 0
#define MAXSI_HTTP_CHUNKED_READING_CHUNK_DATA 1
#define MAXSI_HTTP_CHUNKED_READING_CHUNK_CRLF 2
#define MAXSI_HTTP_CHUNKED_READING_CHUNK_TRAILERS 3

#define MAXSI_HTTP_INTERRUPT_NONE 0
#define MAXSI_HTTP_INTERRUPT_USER 1

//=============================================================================
//	Forward declarations.
//=============================================================================
class IHTTP;

//=============================================================================
//	Define a callback type.
//=============================================================================
typedef size_t (*IHTTPCallback)(BYTE* UserData, IHTTP* Context, BYTE* Buffer, size_t Available);

//=============================================================================
//	Define where the IHTTP interface is declared.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_ABSTRACT_BASECLASS

//=============================================================================
//	Declare the IHTTP Interface.
//=============================================================================
MAXSI_CLASSLINK IHTTP : public MaxsiInterface
{
	MAXSI_DECLARE_INTERFACE(IHTTP);

public:
	virtual MaxsiError Continue() MAXSI_INTERFACE;
	virtual void SetCallback(IHTTPCallback NewCallback) MAXSI_INTERFACE;
	virtual void SetCallbackUserData(BYTE* NewUserData) MAXSI_INTERFACE;
	virtual void SetStream(IBufferStreamer* NewStream) MAXSI_INTERFACE;
	virtual MaxsiError SetMethod(ASCII_t* NewMethod) MAXSI_INTERFACE;
	virtual MaxsiError SetVersion(unsigned int NewMajor, unsigned int NewMinor) MAXSI_INTERFACE;
	virtual MaxsiError SetURLA(char* NewURL) MAXSI_INTERFACE;
	virtual MaxsiError SetURLW(wchar_t* NewURL) MAXSI_INTERFACE;
	virtual MaxsiError SetHost(ASCII_t* NewHost) MAXSI_INTERFACE;
	virtual MaxsiError SetPort(uint16_t	 NewPort) MAXSI_INTERFACE;
	virtual MaxsiError SetResource(ASCII_t* NewResource) MAXSI_INTERFACE;
	virtual MaxsiError SetMimeAttachmentBody(BYTE* Buffer, size_t BufferSize) MAXSI_INTERFACE;
	virtual bool CompareURLsA(char* URL1, char* URL2) MAXSI_INTERFACE;
	virtual bool CompareURLsW(wchar_t* URL1, wchar_t* URL2) MAXSI_INTERFACE;
	virtual uint64_t GetResponseSize() MAXSI_INTERFACE;
	virtual uint64_t GetResponseRead() MAXSI_INTERFACE;
	virtual void Interrupt(int Type, BYTE* UserData) MAXSI_INTERFACE;
	virtual int GetInterruptType() MAXSI_INTERFACE;
	virtual BYTE* GetInterruptData() MAXSI_INTERFACE;
	
};

//=============================================================================
//	Define where the MaxsiHTTP implementation is declared.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_LIBRARY

//=============================================================================
//	Declare the MaxsiHTTP implementation.
//=============================================================================
MAXSI_CLASSLINK MaxsiHTTP : public IHTTP
{
	MAXSI_DECLARE_IMPLEMENTATION(MaxsiHTTP, IHTTP, MAXSI_INTERFACE_DYNAMIC);

public:
	MaxsiHTTP();
	virtual ~MaxsiHTTP();

public:
	BYTE* UserData;
	IHTTPCallback Callback;
	unsigned int Major;
	unsigned int Minor;
	ITCP* Network;
	IBufferStreamer* Stream;
	ASCII_t* RequestHeaders;
	ASCII_t* RequestMethod;
	ASCII_t* HostA;
	MESTR* HostM;
	ASCII_t* Resource;
	bool ShouldMainloop;
	uint16_t Port;
	int State;
	unsigned int ResponseCode;
	unsigned int TransferEncoding;
	unsigned int ChunkedState;
	uint64_t ResponseRead;
	uint64_t ResponseSize;
	uint64_t ContentLength;
#ifdef Maxsi_HTTP_Enable_Entity_Length
	uint64_t EntityLength;
#endif
	uint64_t ChunkSize;
	uint64_t ChunkRead;
	bool ExpectingBody;
	BYTE* MIMEBodyAttachment;
	size_t MIMEBodyAttachmentSize;
	int InterruptType;
	BYTE* InterruptData;
	BYTE* ReceiveBuffer;
	size_t ReceiveBufferSize;
	BYTE* KeepBuffer;
	size_t KeepBufferUsed;
	size_t KeepBufferSize;
	size_t Read;
	size_t Keep;
	size_t LastKeep;

public:
	virtual MaxsiError Connect();
	virtual MaxsiError Disconnect();
	virtual MaxsiError BuildRequest();
	virtual MaxsiError SendRequest();
	virtual MaxsiError ReadResponse();
	virtual MaxsiError ReadResponseHeaders(BYTE* Buffer, size_t Available, size_t* Keep);
	virtual MaxsiError HandleHeader(char* Header, char* Value);
	virtual MaxsiError ReadResponseBody(BYTE* Buffer, size_t Available, size_t* Keep);
	virtual MaxsiError OnActualData(BYTE* Buffer, size_t Available, size_t* Accepted);

public:
	virtual MaxsiError Continue() MAXSI_INTERFACE;
	virtual void SetCallback(IHTTPCallback NewCallback) MAXSI_INTERFACE;
	virtual void SetCallbackUserData(BYTE* NewUserData) MAXSI_INTERFACE;
	virtual void SetNetwork(ITCP* Network) MAXSI_INTERFACE;
	virtual void SetStream(IBufferStreamer* NewStream) MAXSI_INTERFACE;
	virtual MaxsiError SetMethod(ASCII_t* NewMethod) MAXSI_INTERFACE;
	virtual MaxsiError SetVersion(unsigned int NewMajor, unsigned int NewMinor) MAXSI_INTERFACE;
	virtual MaxsiError SetURLA(char* NewURL) MAXSI_INTERFACE;
	virtual MaxsiError SetURLW(wchar_t* NewURL) MAXSI_INTERFACE;
	virtual MaxsiError SetHost(ASCII_t* NewHost) MAXSI_INTERFACE;
	virtual MaxsiError SetPort(uint16_t	 NewPort) MAXSI_INTERFACE;
	virtual MaxsiError SetResource(ASCII_t* NewResource) MAXSI_INTERFACE;
	virtual MaxsiError SetMimeAttachmentBody(BYTE* Buffer, size_t BufferSize) MAXSI_INTERFACE;
	virtual bool CompareURLsA(char* URL1, char* URL2) MAXSI_INTERFACE;
	virtual bool CompareURLsW(wchar_t* URL1, wchar_t* URL2) MAXSI_INTERFACE;
	virtual uint64_t GetResponseSize() MAXSI_INTERFACE;
	virtual uint64_t GetResponseRead() MAXSI_INTERFACE;
	virtual void Interrupt(int Type, BYTE* UserData) MAXSI_INTERFACE;
	virtual int GetInterruptType() MAXSI_INTERFACE;
	virtual BYTE* GetInterruptData() MAXSI_INTERFACE;
	
};

MAXSI_LINK BYTE* CreateHTTPMIMEBodyFileAttachment(char* FileName, BYTE* FileData, size_t FileSize, size_t* ResultSize);
MAXSI_LINK MaxsiError ParseHTTPURL(char* URL, char** HostName, uint16_t* Port, char** Resource);

EndMaxsiNamespace

#endif
